package com.junqson.je.user.controller;

import com.junqson.je.common.annotation.LoginRequire;
import com.junqson.je.common.constant.AppConstant;
import com.junqson.je.common.constant.AppRedisKey;
import com.junqson.je.common.model.ApiResult;
import com.junqson.je.common.model.User;
import com.junqson.je.common.util.AppUtil;
import com.junqson.je.user.client.MsgClient;
import com.junqson.je.user.model.RedisConstants;
import com.junqson.je.user.model.UserModel;
import com.junqson.je.user.service.UserService;
import com.junqson.je.user.utils.ContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Descriptions
 * @Company
 * @Author Junqson
 * @Date 2020/1/20 0:40
 * @Version 1.0
 */
@Slf4j
@RestController
public class LoginController {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    @Autowired
    MsgClient msgClient;

    @Autowired
    ContextUtils contextUtils;

    @Autowired
    UserService userService;

    /**
     * 获取验证码
     *
     * @param phone
     * @return
     */
    @RequestMapping("verify")
    public ApiResult verifiyCode(@RequestParam("phone") String phone) {
        if (!isMObie(phone)) {
            return ApiResult.error("手机号格式错误");
        }

        // 防刷
        String key = AppUtil.getRedisKey(RedisConstants.VC_FS_, phone);
        if (stringRedisTemplate.opsForValue().get(key) != null) {
            return ApiResult.error("验证码请求过于频繁");
        }

        // code
        String code = RandomStringUtils.randomNumeric(6);
        String ck = AppUtil.getRedisKey(RedisConstants.VERIFY_CODE, phone);
        stringRedisTemplate.opsForValue().set(ck, code);

        msgClient.sendCode(phone, code);

        stringRedisTemplate.opsForValue().set(key, " ", RedisConstants.VC_FS_TIME, TimeUnit.SECONDS);

        log.info("手机号[{1}]验证码发送成功！", phone);
        return ApiResult.success();

    }


    /**
     * 登陆
     *
     * @param phone
     * @param code
     * @return
     */
    @RequestMapping("login")
    public ApiResult login(@RequestParam("phone") String phone,
                           @RequestParam("code") String code) {

        if (!isMObie(phone) || !isCode(code)) {
            return ApiResult.error("手机号或验证码格式不正确");
        }

        String token = AppUtil.genUUIDToken(24);
        String tokenK = AppUtil.getRedisKey(AppRedisKey.TOKEN, token);
        Integer userId = 1;

        // 校验验证码
//         测试环境
        if (contextUtils.isDev() && contextUtils.testPhone.equals(phone) && contextUtils.testCode.equals(code)) {
            // dev模式正常登录
            redisTemplate.opsForValue().set(tokenK, userId, AppRedisKey.TOKEN_EXPIRE_MS, TimeUnit.MILLISECONDS);
            Map<String, String> result = new HashMap<>();
            result.put("token", token);
            result.put("userId", userId.toString());
            return ApiResult.success(result);
        } else {
            // 验证码
            String vcKey = AppUtil.getRedisKey(RedisConstants.VERIFY_CODE, phone);
            String vCode = stringRedisTemplate.opsForValue().get(vcKey);
            if (!code.equals(vCode)) {
                return ApiResult.error("验证码错误");
            }
        }

        // 如果用户不存在, 创建新用户
        UserModel thisUser = userService.findByPhone(phone);
        if (thisUser == null) {
            thisUser = userService.createUser(phone);
        }

        userId = thisUser.getUserId();
        userService.updateLastLogin(thisUser);

        // 处理缓存
        String userK = AppUtil.getRedisKey(AppRedisKey.USER_CACHE, userId.toString());
        redisTemplate.opsForValue().set(tokenK, userId, AppRedisKey.TOKEN_EXPIRE_MS, TimeUnit.MILLISECONDS);
        // 验证码用过后清除
        String vcK = AppUtil.getRedisKey(RedisConstants.VERIFY_CODE, phone);
        redisTemplate.delete(vcK);

        User user = new User();
        AppUtil.copyPropertiesIgnoreNull(thisUser, user);
        redisTemplate.opsForValue().set(userK, user);
        //TODO 什么玩意,为啥复制
        Map<String, String> result = new HashMap<>();
        result.put("token", token);
        result.put("userId", userId.toString());
        return ApiResult.success(result);
    }


    /**
     * 注销
     *
     * @return
     */
    @LoginRequire
    @RequestMapping("logout")
    public ApiResult logout(HttpServletRequest request) {
        String auth = request.getHeader(AppConstant.AUTH_HEADER);
        if (StringUtils.isEmpty(auth)) {
            log.error("请求头异常");
            return ApiResult.error();
        }
        // 清除token和user缓存
        String tokenK = AppUtil.getRedisKey(AppRedisKey.TOKEN, auth);
        String uid = stringRedisTemplate.opsForValue().get(tokenK);
        String userK = AppUtil.getRedisKey(AppRedisKey.USER_CACHE, uid);
        redisTemplate.delete(tokenK);
        redisTemplate.delete(userK);

        return ApiResult.success();
    }


    /**
     * 判断是否是手机号
     */
    public static boolean isMObie(String mobie) {
        Pattern p = Pattern.compile("^(13[0-9]|14[57]|15[0-35-9]|16[0-9]|17[0-8]|18[0-9])[0-9]{8}$");
        Matcher m = p.matcher(mobie);
        return m.matches();
    }


    /**
     * 判断验证码格式
     *
     * @param code
     * @return
     */
    public static boolean isCode(String code) {
        Pattern p = Pattern.compile("^\\d{6}$");
        Matcher m = p.matcher(code);
        return m.matches();
    }

}
